package com.xing.web;

import com.google.common.collect.ImmutableMap;
import com.xing.common.PasswordUtil;
import com.xing.dao.rw.UserDao;
import com.xing.dto.UserDto;
import com.xing.entity.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.session.StoppedSessionException;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;

/**
 * Created by Bradish7Y on 2017/9/8.
 */
@Controller
public class UserController {
    public static final Logger log = LoggerFactory.getLogger(UserController.class);

    @RequestMapping(value = "/register", produces = "text/html")
    @ResponseBody
    public String register(String username, String password) {
        User u = new User();
        u.setUsername(username);
        String salt = System.currentTimeMillis() + "";

        u.setPassword(PasswordUtil.generatePassword("md5", password, salt, 2));
        u.setSalt(salt);

        List<User> userList = userDao.selectByMap(ImmutableMap.of("username", username));
        if (!userList.isEmpty()) {
            return "username:" + username + " exists";
        }

        int ret = userDao.insert(u);
        log.info("register ret:{}", ret);
        return "ok";
    }


    @RequestMapping(value = "/login", params = {"kickout"}, method = RequestMethod.GET)
    public String kickout(Model model) {
        UserDto u = new UserDto();
        model.addAttribute("user", u);
        model.addAttribute("message", "you are kickout!!!!");

        return "user/login";
    }

    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String loginForm(Model model) {
        UserDto u = new UserDto();
        model.addAttribute("user", u);
        model.addAttribute("message", "current page is login");

        return "user/login";
    }


    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public String login(@Valid @ModelAttribute("user") UserDto user, HttpServletRequest request, BindingResult bindingResult, RedirectAttributes redirectAttributes) {
        if (bindingResult.hasErrors()) {
            return "login";
        }

        String username = user.getUsername();
        UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword(), user.isRemeberMe());
        //获取当前的Subject
        Subject currentUser = SecurityUtils.getSubject();
        try {
            //在调用了login方法后,SecurityManager会收到AuthenticationToken,并将其发送给已配置的Realm执行必须的认证检查
            //每个Realm都能在必要时对提交的AuthenticationTokens作出反应
            //所以这一步在调用login(token)方法时,它会走到MyRealm.doGetAuthenticationInfo()方法中,具体验证方式详见此方法
            log.info("对用户[" + username + "]进行登录验证..验证开始");
            currentUser.login(token);
            log.info("对用户[" + username + "]进行登录验证..验证通过");
        } catch (UnknownAccountException uae) {
            log.info("对用户[" + username + "]进行登录验证..验证未通过,未知账户");
            redirectAttributes.addFlashAttribute("message", "未知账户");
        } catch (IncorrectCredentialsException ice) {
            log.info("对用户[" + username + "]进行登录验证..验证未通过,错误的凭证");
            redirectAttributes.addFlashAttribute("message", "密码不正确");
        } catch (LockedAccountException lae) {
            log.info("对用户[" + username + "]进行登录验证..验证未通过,账户已锁定");
            redirectAttributes.addFlashAttribute("message", "账户已锁定");
        } catch (ExcessiveAttemptsException eae) {
            log.info("对用户[" + username + "]进行登录验证..验证未通过,错误次数过多");
            redirectAttributes.addFlashAttribute("message", "用户名或密码错误次数过多");
        } catch (AuthenticationException ae) {
            //通过处理Shiro的运行时AuthenticationException就可以控制用户登录失败或密码错误时的情景
            log.info("对用户[" + username + "]进行登录验证..验证未通过,堆栈轨迹如下");
            ae.printStackTrace();
            redirectAttributes.addFlashAttribute("message", "用户名或密码不正确");
        }
        //验证是否登录成功
        if (currentUser.isAuthenticated()) {

            log.info("用户[" + username + "]登录认证通过(这里可以进行一些认证通过后的一些系统参数初始化操作)");
            return "redirect:/index";
        } else {
            token.clear();
            return "redirect:/login";
        }
    }

    @RequestMapping(value = "/logout", method = {RequestMethod.GET, RequestMethod.POST})
    public String logout(RedirectAttributes redirectAttributes) {
        try {
            SecurityUtils.getSubject().logout();
        } catch (StoppedSessionException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

        //redirectAttributes.addFlashAttribute("message", "您已安全退出");
        return "redirect:/login";
    }

    @RequestMapping("/403")
    public String unauthorizedRole() {
        log.info("------没有权限-------");
        return "403";
    }

    @RequestMapping(value = "/user", produces = "application/json")
    @ResponseBody
    public List<User> getUserList(Map<String, Object> model) {
        return userDao.listUser();
    }


    @Resource
    private UserDao userDao;
}
